#ifndef __GLF_FSTL_fixed_alloc_H_INCLUDED__
#define __GLF_FSTL_fixed_alloc_H_INCLUDED__

#include <glf/config.h>
#include <glf/core/inlines.h>

namespace glf {



struct fixed_alloc_info : public NonCopyable {
	size_t allocated;
	size_t capacity;
	char* buffer;
};

template <class T>
 struct fixed_alloc {
	typedef T				value_type;
	typedef T*				pointer;
	typedef const T*		const_pointer;
	typedef T&				reference;
	typedef const T&		const_reference;
	typedef std::size_t		size_type;
	typedef std::ptrdiff_t	difference_type;

	// rebind allocator to type U
	template <class U>
	struct rebind {
		typedef fixed_alloc<U> other;
	};

	pointer address (reference value) const {
		return &value;
	}
	const_pointer address (const_reference value) const {
		return &value;
	}

	fixed_alloc(fixed_alloc_info& info, char* buffer, size_t sizeofBuffer) :
		mInfo(info)
	{
		mInfo.buffer = buffer;
		mInfo.capacity = sizeofBuffer;
		mInfo.allocated = 0;
	}
	// throw() { }
	fixed_alloc(const fixed_alloc& other) throw()  :
		mInfo(other.mInfo)
	{

	}
	//
	//fixed_alloc& operator=(const fixed_alloc& other) {
	//	if(this != & other) {
	//		this->mInfo = other.mInfo;
	//	}
	//	return *this;
	//}
	
	template <class U>
	fixed_alloc (const fixed_alloc<U>& other) throw() :
		mInfo(other.mInfo)
	{ 

	}

	~fixed_alloc() throw() 
	{

	}

	size_type max_size () const throw() {
		return mInfo.capacity / sizeof(T);
	}

	pointer allocate (size_type num, const void* = 0) {
		size_t toAllocate = num * sizeof(T);

		GLFi_ASSERT(mInfo.allocated + toAllocate <= mInfo.capacity);

		pointer p = (pointer)(mInfo.buffer + mInfo.allocated);
		
		mInfo.allocated += toAllocate;

		return p;
	}

	void construct (pointer p, const T& value) {
		new (p) T(value);
	}

	void destroy (pointer p) {
		p->~T();
	}

	void deallocate (pointer p, size_type num) {
		void* ptr = p;

		GLFi_ASSERT(ptr >= mInfo.buffer && ptr <= mInfo.buffer+mInfo.capacity);
	}
	
	fixed_alloc_info& mInfo;
 private:
	 fixed_alloc();
	 fixed_alloc& operator=(const fixed_alloc& other);
	 
	
};

// return that all specializations of this allocator are interchangeable
template <class T1, class T2>
bool operator== (const fixed_alloc<T1>&, const fixed_alloc<T2>&) throw() {
   return true;
}
template <class T1, class T2>
bool operator!= (const fixed_alloc<T1>&, const fixed_alloc<T2>&) throw() {
   return false;
}
} //namespace glf

#endif
